package com.yantong.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yantong.enums.PayChannelEnum;
import com.yantong.mapper.*;
import com.yantong.pay.yfz.domain.pay.domain.withdraw.WithdrawToCardResponse;
import com.yantong.pay.yfz.pay.YFZPayutil;
import com.yantong.pojo.*;
import com.yantong.service.*;
import com.yantong.constant.*;
import com.yantong.exception.BDException;
import com.yantong.utils.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author kanghaixin
 * @date 2018/9/16.21:07
 */
@Service
public class WithdrawalsServiceImpl implements WithdrawalsService {
	@Autowired
	private WithdrawalsMapper withdrawalsMapper;
	@Autowired
	private BalanceService balanceService;
	@Autowired
	@Lazy
	private PayService payService;
	@Autowired
	private MemberService memberService;
	@Autowired
	private OrderWithdrawalsMapper orderWithdrawalsMapper;
	@Autowired
	private MemberMapper memberMapper;
	@Autowired
	private BalanceLogService balanceLogService;
	@Autowired
	private BalanceLogMapper balanceLogMapper;
	@Autowired
	private CentreMapper centreMapper;
	@Autowired
	private CentreService centreService;
	@Autowired
	private PayChannelService payChannelService;
	private static final Logger logger = LoggerFactory.getLogger(WithdrawalsServiceImpl.class);

	@Override
	public PageUtils<Withdrawals> listWithdrawals(WdListParams wdListParams, int offset, int limit) {
		PageUtils<Withdrawals> pageUtils = new PageUtils<>();

		int total = withdrawalsMapper.countByParams(wdListParams);
		if (total > 0) {
			pageUtils.setTotal(total);
			pageUtils.setRows(withdrawalsMapper.listByParams(wdListParams, new RowBounds(offset, limit)));
		}
		return pageUtils;
	}


	/**
	 * 根据状态查找第三方代付记录表
	 *
	 * @param transts
	 * @param rowBounds
	 * @return
	 */
	public PageUtils<OrderWithdrawals> getOrderWithdrawalsByTransts(WdListParams wdListParams, int offset, int limit) {
		PageUtils<OrderWithdrawals> pageUtils = new PageUtils<OrderWithdrawals>();

		int total = orderWithdrawalsMapper.countByParams(wdListParams);
		if (total > 0) {
			pageUtils.setTotal(total);
			pageUtils.setRows(orderWithdrawalsMapper.getOrderWithdrawalsByTransts(wdListParams, new RowBounds(offset, limit)));
		}
		return pageUtils;
	}

	/**
	 * 根据状态查找第三方代付记录表 无分页
	 *
	 * @return
	 */
	public List<OrderWithdrawals> getOrderWithdrawalsByTranstsList(WdListParams wdListParams) {
		return orderWithdrawalsMapper.getOrderWithdrawalsByTranstsList(wdListParams);
	}

	@Override
	public BigDecimal getMemberCashedCount(Long memberId) {
		return withdrawalsMapper.getMemberCashedCount(memberId);
	}

	@Override
	public List<Withdrawals> listWithdrawals(WdListParams params) {
		return withdrawalsMapper.listByParams(params);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int updateWithdrawals(Withdrawals withdrawals) {
		if (withdrawals == null || withdrawals.getId() == null) {
			return 0;
		}
		return withdrawalsMapper.updateByPrimaryKeySelective(withdrawals);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int cashRefuse(Long bwId, Long aid, String aName) {
		if (bwId == null) {
			return 0;
		}
		int result = 0;
		Withdrawals withdrawals = withdrawalsMapper.selectByPrimaryKey(bwId);
		if (withdrawals == null) {
			logger.info("not found withdrawals by id:{}", bwId);
			return 0;
		}
		//如果提现角色为供应商角色则应该退至供应商余额
		if (withdrawals.getRole() == 1) {
		} else {
			//否则退至门店与普通用户余额
			result = balanceService.recharge(withdrawals.getMid(), withdrawals.getMoney().doubleValue(),
					BalanceLogStyle.CASH_REFUND.getCode(), RechargeType.CASH_REFUND.getType(), withdrawals.getApplyno());
		}


		if (result > 0) {
			withdrawals.setCheckName(aName);
			withdrawals.setCheckId(aid);
			withdrawals.setCheckTime(new Date());
			withdrawals.setStatus(CashStatus.DISABLED.getCode());
			return withdrawalsMapper.updateByPrimaryKeySelective(withdrawals);
		}
		return 0;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int offlinePay(Long bwId, Long payId, String payName) {
		if (bwId == null) {
			return 0;
		}
		Withdrawals wd = withdrawalsMapper.selectByPrimaryKey(bwId);
		if (wd == null) {
			return 0;
		}
		wd.setPayId(payId);
		wd.setPayName(payName);
		wd.setPayTime(new Date());
		wd.setStatus(CashStatus.COMPLETED.getCode());
		wd.setType(0);
		return withdrawalsMapper.updateByPrimaryKeySelective(wd);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int wxPay(Long bwId, Long payId, String payName) {
		if (bwId == null) {
			return 0;
		}
		Withdrawals wd = withdrawalsMapper.selectByPrimaryKey(bwId);
		if (wd == null) {
			return 0;
		}
		wd.setId(bwId);
		wd.setPayTime(new Date());
		wd.setPayId(payId);
		wd.setType(1);
		wd.setPayName(payName);
		wd.setStatus(CashStatus.COMPLETED.getCode());
		int updateResult = withdrawalsMapper.completeApply(wd);
		if (updateResult < 1) {
			return 0;
		}

		if (wd.getMoney() != null) {
			// CentreAmount ca =
			// centreService.getAmountByCentreId(wd.getCentreId());
			// if (ca == null) {
			// return 0;
			// }
			// if (ca.getAmount().doubleValue() < wd.getMoney().doubleValue()) {
			// throw new BDException(BusinessCode.CENTER_AMOUNT_NO_BALANCE);
			// }
			Member member = memberService.getByKey(wd.getMid());
			if (member == null || StringUtils.isEmpty(member.getOpenid())) {
				return 0;
			}
			logger.info("微信企业支付:{}", wd.getApplyno());
			String pr = "";
			Centre centre = centreMapper.selectByPrimaryKey(wd.getCentreId());
			if (centre != null && StringUtils.isNotEmpty(centre.getRelateAccount())) {
				//商户开的小程序
				pr = payService.enterpriceToCustomerByCentre(member.getOpenid(),
						wd.getMoney().multiply(BigDecimal.valueOf(100)).doubleValue(), member.getRealname(),
						wd.getApplyno(), "企业付款到零钱_" + wd.getApplyno(), centre, member.getAppOpenid());
			} else {
				pr = payService.enterpriceToCustomer(member.getOpenid(),
						wd.getMoney().multiply(BigDecimal.valueOf(100)).doubleValue(), member.getRealname(),
						wd.getApplyno(), "企业付款到零钱_" + wd.getApplyno());
			}
			if (StringUtils.isEmpty(pr)) {
				logger.info("微信支付失败");
				throw new BDException("微信企业支付失败");
			}
			wd.setPaymentNo(pr);
		}
		return withdrawalsMapper.updateByPrimaryKeySelective(wd);
	}




	@Override
	@Transactional(rollbackFor = Exception.class)
	public int yfzBankPay(Long bwId, Long payId, String payName) {
		try {
			if (bwId == null) {
				return 0;
			}
			Withdrawals wd = withdrawalsMapper.selectByPrimaryKey(bwId);
			if (wd == null || wd.getStatus() == CashStatus.COMPLETED.getCode()) {
				return 0;
			}
			if (org.springframework.util.StringUtils.isEmpty(wd.getBankcard())) {
				return 0;
			}
			wd.setId(bwId);
			wd.setPayTime(new Date());
			wd.setPayId(payId);
			wd.setType(2);
			wd.setPayName(payName);
			wd.setStatus(CashStatus.COMPLETED.getCode());
			withdrawalsMapper.updateByPrimaryKeySelective(wd);   //首先设置为已打款，实际是否打款根据下面逻辑重新更新状态，防止重复打款

			if (wd.getMoney() != null) {
				Member member = memberService.getByKey(wd.getMid());
				if (member == null || StringUtils.isEmpty(member.getOpenid())) {
					return 0;
				}
				logger.info("易票联代付支付:{}", wd.getApplyno());
				double payAmt = Double.valueOf(wd.getMoney() + "");
				String desc = "提现".concat(",操作人:").concat(ShiroUtils.getUser().getNickname());

				PayChannel payChannel = payChannelService.getFirstChannel(wd.getCentreId());
				WithdrawToCardResponse withdrawToCardResponse = null;
				if (StringUtils.isNotBlank(payChannel.getChannelCode()) && payChannel.getChannelCode().equals(PayChannelEnum.YPL.getCode())) {
					//获取商户支付参数
					Centre centre = centreService.getCentreById(wd.getCentreId());
					Map<String, String> map = new HashMap<>();
					map.put("yplSignNo", centre.getYplSignNo());
					map.put("yplCustomerCode", centre.getYplCustomerCode());
					map.put("yplPrivateKey", centre.getYplPrivateKey());
					map.put("yplPublicKey", centre.getYplPublicKey());
					map.put("yplPrivateKeyPwd", centre.getYplPrivateKeyPwd());
					//yfz提现打款
					withdrawToCardResponse = YFZPayutil.withdrawalToCard(map, "", wd);
					logger.error("代付返回参数："+JSONObject.toJSONString(withdrawToCardResponse));
				} else {
					throw new BDException("该支付通道暂无打款记录！");
				}

				if (withdrawToCardResponse == null) {
					return 0;
				}
				wd.setId(bwId);
				// 更新易票联流水号
				wd.setPaymentNo(withdrawToCardResponse.getTransactionNo());
				//首先设置为已打款，实际是否打款根据下面逻辑重新更新状态，防止重复打款
				withdrawalsMapper.updateByPrimaryKeySelective(wd);

				// 构建打款记录
				OrderWithdrawals order = new OrderWithdrawals();
				order.setCredt(new Date());
				order.setBankcard(wd.getBankcard());//银行卡号
				order.setCashamt(wd.getMoney());//发起转账金额
				order.setChanelcode(PayChannelEnum.YPL.getCode());//提现通道编号
				order.setChanelnm(PayChannelEnum.YPL.getValue());//提现通道名
				order.setMemid(wd.getMid() + "");//会员ID
				order.setMemrealnm(wd.getRealname());//提现人真实姓名
				order.setServcarge(new BigDecimal("0"));//提现手续费
				order.setSpid(ConfigUtil.getProperty("HJ_userNo"));//汇聚商户号
				order.setTranceamt(new BigDecimal(payAmt + ""));//实际转账金额
				order.setUpddt(new Date());
				order.setUserid(wd.getCheckId() + "");//记录操作人id
				order.setUsername(wd.getCheckName());//记录操作人
				order.setWithid(bwId + "");//记录 提现记录编号
				order.setCentreId(member.getCentreId());//记录服务中心id
				order.setRecordtyp(0);//记录类型为会员/供应商打款
				//处理中 未知 受理成功
				if ( /*resultMap.get("statusCode").toString().equals("2003") ||*/
						!withdrawToCardResponse.getReturnCode().equals("0000")) {
					order.setTransts(1);//更新为正在处理中
					order.setSerialnostate("2");//第三方状态
					order.setTfbserialno(withdrawToCardResponse.getTransactionNo());// 更新汇聚签名
					orderWithdrawalsMapper.insertSelective(order);// 插入转账记录数据

					wd.setStatus(5);//如果处理中 则更新记录为天付宝打款失败 或汇聚
					withdrawalsMapper.updateByPrimaryKeySelective(wd);//更新提现记录
					return 0;

				}                // 处理失败
				else {
					//余额变更记录
					BalanceLog log = new BalanceLog();
					order.setSerialnostate("3");
					order.setTransts(3);
					wd.setStatus(4);//将申请记录更新为打款失败
					if (!org.springframework.util.StringUtils.isEmpty(wd.getRole()) && wd.getRole() == 1) {
						log.setMid(member.getId());
						log.setMobile(member.getMobile());
						log.setRealname(member.getRealname());
						log.setStatus(0);
						log.setType(1);
						log.setStyle(7);
						log.setCredittype("credit2");
						log.setMoney(wd.getMoney());
						log.setCreateTime(new Date());
						log.setCentreId(member.getCentreId());
						log.setTitle("提现失败");
						log.setRemark("供应商提现，回调提现失败,供应商余额变更记录 【提现单号：" + wd.getApplyno() + "】" + "错误:" + withdrawToCardResponse.getReturnMsg());
						log.setSource(2);//供应商余额变更
						log.setFlowtype("13");//流水类型:供应商提现失败
						balanceLogService.save(log);
						//供应商退供应商余额
					} else {
						log.setMid(member.getId());
						log.setMobile(member.getMobile());
						log.setRealname(member.getRealname());
						log.setStatus(0);
						log.setType(1);
						log.setStyle(7);
						log.setCredittype("credit2");
						log.setBeforeamount(member.getCredit2());
						log.setMoney(wd.getMoney());
						log.setAfteramount(member.getCredit2().add(wd.getMoney()));
						log.setCreateTime(new Date());
						log.setCentreId(member.getCentreId());
						log.setTitle("提现失败");
						log.setRemark("会员提现，回调提现失败，会员余额变更记录 【提现单号：" + wd.getApplyno() + "】" + "错误:" + withdrawToCardResponse.getReturnMsg());
						log.setSource(0);//供应商余额变更
						//判断提现记录申请角色 如果是会员 则  //流水类型:用户提现失败 否则 流水类型:门店提现失败
						log.setFlowtype(wd.getRole() == 0 ? "2" : "7");
						balanceLogService.save(log);
						//其他提现退会员余额
						memberMapper.rechargeBalance(member.getId(), Double.valueOf(wd.getMoney() + ""));
					}
					orderWithdrawalsMapper.insertSelective(order);// 插入转账记录数据
					return withdrawalsMapper.updateByPrimaryKeySelective(wd);//更新提现记录
				}

			}
		} catch (Exception e) {
			e.printStackTrace();

		}
		return 1;
	}




	@Override
	@Transactional(rollbackFor = Exception.class)
	public int batchUpdateBankPay(Long bwId, Long payId, String payName) {
		try {
			if (bwId == null) {
				return 0;
			}

			//根据记录编号查询打款处理中记录
			OrderWithdrawals orderWithdrawals = orderWithdrawalsMapper.selectByPrimaryKey(bwId);
			if (orderWithdrawals == null) {
				//如果不存在打款记录则直接返回
				return 0;
			}
			Withdrawals wd = withdrawalsMapper.selectByPrimaryKey(Long.valueOf(orderWithdrawals.getWithid()));
			wd.setId(Long.valueOf(orderWithdrawals.getWithid()));
			wd.setPayTime(new Date());
			wd.setPayId(payId);
			wd.setType(1);
			wd.setPayName(payName);
			//wd.setStatus(CashStatus.COMPLETED.getCode());

			Map<String, Object> params = new HashMap<String, Object>();
			if (wd.getMid() != null) {
				params.put("mid", wd.getMid());
			}
			if (wd.getMoney() != null) {
				params.put("money", wd.getMoney());
			}
			if (wd.getCentreId() != null) {
				params.put("centreId", wd.getCentreId());
			}
			if (StringUtils.isNotEmpty(wd.getApplyno())) {
				params.put("remark", wd.getApplyno());
			}
			List<BalanceLog> logList = balanceLogMapper.BalanceLoglistByParams(params);
			if (CollectionUtils.isNotEmpty(logList)) {
				return 0;
			}

			Member member = memberService.getByKey(wd.getMid());
			//PaySigleResVo raySigleResVo = new PaySigleResVo();//开始组装回调参数
			//raySigleResVo.setSpid(ConfigUtil.getProperty("TFB_spid"));//天付宝商户号
			/*raySigleResVo.setSpid(ConfigUtil.getProperty("HJ_userNo"));//汇聚商户号
			raySigleResVo.setSpSerialno(orderWithdrawals.getSpserialno());//商户代付单号
			raySigleResVo.setTfbSerialno(orderWithdrawals.getTfbserialno());//天付宝代付单号
*/            //Map<String, Object> paySigleConfig = TFBPayOtherUtil.getQueryPaySigleConfig(raySigleResVo);//发起查询
			Map<String, Object> paySigleConfig = SinglePayQuery.singlePayQueryInfo(orderWithdrawals.getTfbserialno());//发起查询
			//天付宝返回为空说明入参错误直接返回
			if (paySigleConfig == null) return 0;



			/*	if (paySigleConfig.get("serialno_state")!=null&&(paySigleConfig.get("serialno_state") + "").equals("1")) {*/
			//受理成功
			if (paySigleConfig.get("statusCode").toString().equals("2001") && paySigleConfig.get("status").toString().equals("205")) {
				//天付宝查询代付结果成功后   更新转账记录新结果 更新申请记录结果
				//orderWithdrawals.setSerialnostate(paySigleConfig.get("serialno_state") + "");
				orderWithdrawals.setSerialnostate("1");//处理成功
				orderWithdrawals.setUpddt(new Date());
				orderWithdrawals.setTransts(2);//转账完成
				orderWithdrawals.setSpserialno(paySigleConfig.get("platformSerialNo").toString());
				orderWithdrawalsMapper.updateByPrimaryKeySelective(orderWithdrawals);// 更新转账记录数据
				//wd.setPaymentNo(paySigleConfig.get("tfb_serialno") + "");// 更新天付宝代付单号
				wd.setPaymentNo(paySigleConfig.get("merchantOrderNo") + "");// 更新汇聚平台流水号
				wd.setStatus(3);//将申请记录更新为已打款


				//打款成功也插入余额变更记录，
				BalanceLog log = new BalanceLog();
				log.setMid(member.getId());
				log.setMobile(member.getMobile());
				log.setRealname(member.getRealname());
				log.setStatus(0);
				log.setType(1);
				log.setStyle(7);
				log.setCredittype("credit2");
				log.setBeforeamount(member.getCredit2());
				log.setMoney(new BigDecimal("0"));//提现成功流水变更金额为0
				log.setAfteramount(member.getCredit2());
				log.setCreateTime(new Date());
				log.setCentreId(member.getCentreId());
				log.setSource(0);//供应商余额变更
				//判断提现记录申请角色
				if (wd.getRole() == 0) {
					log.setFlowtype("1"); //流水类型:用户提现
					log.setTitle("会员提现成功");
					log.setMoney(wd.getMoney() == null ? new BigDecimal("0") : wd.getMoney());
					log.setRemark("会员提现成功 【提现单号：" + wd.getApplyno() + "】");
				} else if (wd.getRole() == 1) {
					//流水类型:供应商提现
					//供应商提现余额
					log.setMoney(wd.getMoney() == null ? new BigDecimal("0") : wd.getMoney());
					// log.setAfteramount(supply.getBalance().add(wd.getMoney()));
					//供应商提现之后余额
					log.setFlowtype("12");
					log.setTitle("供应商提现成功");
					//把来源修改为供应商用户
					log.setSource(2);
					log.setRemark("供应商提现成功 【提现单号：" + wd.getApplyno() + "】");
				} else if (wd.getRole() == 3) {
					log.setFlowtype("6");  //流水类型:门店提现
					log.setTitle("门店提现成功");
					log.setRemark("门店提现成功 【提现单号：" + wd.getApplyno() + "】");
				}

				balanceLogService.save(log);
				return withdrawalsMapper.updateByPrimaryKeySelective(wd); //更新申请记录
			}/*else if (paySigleConfig.get("serialno_state")!=null&&(paySigleConfig.get("serialno_state") + "").equals("2")) {*/
			// 处理中
			else if (paySigleConfig.get("statusCode").toString().equals("2001") && paySigleConfig.get("status").toString().equals("203")) {
				return 0;
			}/*else if (paySigleConfig.get("serialno_state")!=null&&(paySigleConfig.get("serialno_state") + "").equals("3")) {*/
			// 处理失败
			else if (paySigleConfig.get("statusCode").toString().equals("2001") && paySigleConfig.get("status").toString().equals("204")) {
				//余额变更记录
				BalanceLog log = new BalanceLog();
				if (!org.springframework.util.StringUtils.isEmpty(wd.getRole()) && wd.getRole() == 1) {
					log.setMid(member.getId());
					log.setMobile(member.getMobile());
					log.setRealname(member.getRealname());
					log.setStatus(0);
					log.setType(1);
					log.setStyle(7);
					log.setCredittype("credit2");
					log.setMoney(wd.getMoney());
					log.setCreateTime(new Date());
					log.setCentreId(member.getCentreId());
					log.setTitle("提现失败");
					log.setRemark("供应商提现，回调提现失败,供应商余额变更记录 【提现单号：" + wd.getApplyno() + "】" + "错误:" + paySigleConfig.get("errorDesc"));
					log.setSource(2);//供应商余额变更
					log.setFlowtype("13");//流水类型:供应商提现失败
					balanceLogService.save(log);
					//供应商退供应商余额
				} else {
					log.setMid(member.getId());
					log.setMobile(member.getMobile());
					log.setRealname(member.getRealname());
					log.setStatus(0);
					log.setType(1);
					log.setStyle(7);
					log.setCredittype("credit2");
					log.setBeforeamount(member.getCredit2());
					log.setMoney(wd.getMoney());
					log.setAfteramount(member.getCredit2().add(wd.getMoney()));
					log.setCreateTime(new Date());
					log.setCentreId(member.getCentreId());
					log.setTitle("提现失败");
					log.setRemark("会员提现，回调提现失败，会员余额变更记录 【提现单号：" + wd.getApplyno() + "】" + "错误:" + paySigleConfig.get("errorDesc"));
					log.setSource(0);//供应商余额变更
					//判断提现记录申请角色 如果是会员 则  //流水类型:用户提现失败 否则 流水类型:门店提现失败
					log.setFlowtype(wd.getRole() == 0 ? "2" : "7");
					balanceLogService.save(log);
					//其他提现退会员余额
					memberMapper.rechargeBalance(member.getId(), Double.valueOf(wd.getMoney() + ""));
				}

				orderWithdrawals.setTransts(3);
				orderWithdrawals.setSpserialno(paySigleConfig.get("platformSerialNo").toString());
				int result = orderWithdrawalsMapper.updateByPrimaryKeySelective(orderWithdrawals);// 插入转账记录数据
				if (result != 1) throw new BDException(BusinessCode.TFB_DF_FAIL1);

				wd.setStatus(4);//将申请记录更新为打款失败
				return withdrawalsMapper.updateByPrimaryKeySelective(wd);//更新提现记录
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return 1;
	}

}
